package com.vcc.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.vcc.core.enumConstant.RoleEnum;
import com.vcc.core.exception.NotFoundException;
import com.vcc.core.exception.ProgramException;
import com.vcc.data.entity.Role;
import com.vcc.data.entity.UserRole;
import com.vcc.data.mapper.RoleMapper;
import com.vcc.service.boss.request.clientRole.BossClientRoleUpdateRequest;
import com.vcc.service.boss.response.clientRole.ClientRoleVoBoss;
import com.vcc.service.client.vo.role.RoleVo;
import com.vcc.service.sa.BossUserUtil;
import com.vcc.service.service.RoleService;
import com.vcc.service.service.UserRoleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;

import static com.vcc.data.entity.table.BossUserTableDef.BOSS_USER;
import static com.vcc.data.entity.table.RoleTableDef.ROLE;
import static com.vcc.data.entity.table.UserRoleTableDef.USER_ROLE;
import static com.vcc.data.entity.table.UserTableDef.USER;

@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    @Autowired
    private UserRoleService userRoleService;


    @Override
    public Role getRole(Long userId) {
        QueryChain<Role> roleQueryChain = queryChain();
        roleQueryChain.select(ROLE.ALL_COLUMNS);
        roleQueryChain.leftJoin(USER_ROLE.as("ur")).on(USER_ROLE.ROLE_ID.eq(ROLE.ID));
        roleQueryChain.where(USER_ROLE.USER_ID.eq(userId));
        return roleQueryChain.oneOpt().orElseThrow(() -> new NotFoundException("没有当前权限"));
    }

    @Override
    public List<Role> getRole(List<Long> userId) {
        QueryChain<Role> roleQueryChain = queryChain();
        roleQueryChain.select(ROLE.ALL_COLUMNS);
        roleQueryChain.leftJoin(USER_ROLE.as("ur")).on(USER_ROLE.ROLE_ID.eq(ROLE.ID));
        roleQueryChain.where(USER_ROLE.USER_ID.in(userId));
        return roleQueryChain.list();
    }

    @Override
    public Role getByRoleEnum(RoleEnum roleEnum) {
        return queryChain().eq(Role::getCode, roleEnum.getValue()).oneOpt().orElseThrow(() -> new NotFoundException("没有当前权限"));
    }

    @Override
    public Boolean existsById(Long id) {
        return queryChain().eq(Role::getId, id).exists();
    }

    @Override
    public Role getById(Long id) {
        return queryChain().eq(Role::getId, id).oneOpt().orElseThrow(() -> new NotFoundException("没有当前权限"));
    }

    @Override
    public Boolean init(RoleEnum roleEnum, Long userId) {
        Role role = getByRoleEnum(roleEnum);
        userRoleService.save(new UserRole(userId, role.getId()));
        return true;
    }

    @Override
    public Boolean init(Long roleId, Long userId) {
        Role role = getById(roleId);
        if (role == null) {
            throw new ProgramException("没有当前角色");
        }
        userRoleService.save(new UserRole(userId, role.getId()));
        return true;
    }

    @Override
    public Boolean updateUserRole(Long userId, Long id, Long sourceId) {
        int row = mapper.updateRoleByUserId(userId, id, sourceId);
        return row > 0;
    }

    @Override
    public List<Role> listByUserIds(Collection<Long> userIds) {
        return null;
    }

    @Override
    public List<RoleVo> listByUserId(Role role, Long userId, String code, String name) {
        QueryChain<Role> roleQueryChain = queryChain();
        roleQueryChain.select(ROLE.ALL_COLUMNS);
        if (role.getHasAllData()) {
            roleQueryChain.leftJoin(USER).on(USER.ID.eq(ROLE.USER_ID)).where(USER.PARENT_ID.eq(userId).or(USER.ID.eq(userId)));
        } else {
            roleQueryChain.eq(Role::getUserId, userId);
        }
        if (StringUtils.isNotBlank(code)) {
            roleQueryChain.and(ROLE.CODE.like("%" + code + "%"));
        }
        if (StringUtils.isNotBlank(name)) {
            roleQueryChain.and(ROLE.NAME.like("%" + name + "%"));
        }
        return listAs(roleQueryChain, RoleVo.class);
    }

    @Override
    public Page<RoleVo> paging(Integer pagNumber, Integer pageSize, Role role, Long userId, String code, String name) {
        QueryChain<Role> roleQueryChain = queryChain();
        roleQueryChain.select(ROLE.ALL_COLUMNS);
        if (role.getHasAllData()) {
            roleQueryChain.leftJoin(USER).on(USER.ID.eq(ROLE.USER_ID)).where(USER.PARENT_ID.eq(userId).or(USER.ID.eq(userId)));
        } else {
            roleQueryChain.eq(Role::getUserId, userId);
        }

        if (StringUtils.isNotBlank(code)) {
            roleQueryChain.and(ROLE.CODE.like("%" + code + "%"));
        }
        if (StringUtils.isNotBlank(name)) {
            roleQueryChain.and(ROLE.NAME.like("%" + name + "%"));
        }
        return pageAs(
                Page.of(
                        pagNumber == null ? 1 : pagNumber,
                        pageSize == null ? 20 : pageSize
                ),
                roleQueryChain,
                RoleVo.class
        );
    }

    @Override
    public boolean existsByUserIdAndCode(Long userId, String code) {
        return queryChain().eq(Role::getUserId, userId).eq(Role::getCode, code).exists();
    }

    @Override
    public boolean updateNameAndHasAllDataById(Long id, String name, Boolean hasAllData) {
        return updateChain().set(ROLE.NAME, name)
                .set(ROLE.HAS_ALL_DATA, hasAllData)
                .where(ROLE.ID.eq(id))
                .update();
    }

    @Override
    public Page<ClientRoleVoBoss> paging(Page<ClientRoleVoBoss> page, Long userId, String code, String name) {
        QueryChain<Role> roleQueryChain = queryChain();
        roleQueryChain
                .select(USER.ACCOUNT.as("account"))
                .select(ROLE.ALL_COLUMNS);
        roleQueryChain.leftJoin(USER).on(USER.ID.eq(ROLE.USER_ID));
        Long bossUserId = BossUserUtil.getIdNotNull();
        if (!BossUserUtil.hasAllData()) {
            roleQueryChain.leftJoin(BOSS_USER.as("dealer")).on(USER.BE_LONG_TO_DEALER.eq(BOSS_USER.ID));
            roleQueryChain.and(
                    BOSS_USER.as("dealer").ID.eq(bossUserId)
                            .or(BOSS_USER.as("dealer").PARENT_ID.eq(bossUserId))
            );
        }
        if (userId != null) {
            roleQueryChain.where(ROLE.USER_ID.eq(userId));
        }
        if (code != null) {
            roleQueryChain.where(ROLE.CODE.eq(code));
        }
        if (name != null) {
            roleQueryChain.where(ROLE.NAME.like(name));
        }
        roleQueryChain.orderBy(ROLE.CREATE_DATE, false);
        return roleQueryChain.pageAs(page, ClientRoleVoBoss.class);

    }

    @Override
    public Boolean existsByCodeAndUserId(String code, Long userId) {
        return queryChain().eq(Role::getCode, code).eq(Role::getUserId, userId).exists();
    }

    @Override
    public Boolean existsByNameAndUserId(String name, Long userId) {
        return queryChain().eq(Role::getName, name).eq(Role::getUserId, userId).exists();
    }

    @Override
    public Boolean existsByHasClientIntoRole(Boolean hasClientIntoRole) {
        return queryChain().eq(Role::getHasClientIntoRole, hasClientIntoRole).exists();
    }

    @Override
    public Role getClientInitRole() {
        return queryChain().eq(Role::getHasClientIntoRole, true).oneOpt().orElseThrow(() -> new NotFoundException("没有当前权限"));
    }

    @Override
    public Boolean updateRole(BossClientRoleUpdateRequest bossClientRoleUpdateRequest) {
        Role role = getById(bossClientRoleUpdateRequest.getId());
        //当前角色不是初始化角色，且更新的角色是初始化角色
        if (!role.getHasClientIntoRole() && bossClientRoleUpdateRequest.getHasClientIntoRole()) {
            if (existsByHasClientIntoRole(true)) {
                throw new ProgramException("已经存在初始化角色无法修改当前角色为初始化角色");
            }
        }
        UpdateChain<Role> updateChain = updateChain();
        if (!role.getName().equals(bossClientRoleUpdateRequest.getName())) {
            if (existsByNameAndUserId(bossClientRoleUpdateRequest.getName(), bossClientRoleUpdateRequest.getUserId())) {
                throw new ProgramException("角色名称已存在");
            }
            updateChain.set(Role::getName, bossClientRoleUpdateRequest.getName());
        }
        updateChain.set(Role::getHasClientIntoRole, bossClientRoleUpdateRequest.getHasClientIntoRole())
                .set(Role::getHasClientUpdate, bossClientRoleUpdateRequest.getHasClientUpdate())
                .set(Role::getHasAllData, bossClientRoleUpdateRequest.getHasAllData())
                .eq(Role::getId, bossClientRoleUpdateRequest.getId())
                .update();
        return true;
    }

    @Override
    public List<Role> listByCode(String code) {
        return queryChain().eq(Role::getCode, code).list();
    }
}
